package com.yq.testmodule.view

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.ScrollingView
import androidx.customview.widget.ViewDragHelper
import com.fmt.mvi.learn.gobal.log


enum class DragViewState {
    OPEN, CLOSE, OPENING
}

class DragViewLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {


    lateinit var mContentView: View
    lateinit var mDragView: View
    lateinit var mDragHelper: ViewDragHelper

    var maxDragHeight = resources.displayMetrics.heightPixels * 9 / 16 // 可拖拽view的高度
        set(value) {
            field = value
            //requestLayout 可能不会触发onMeasure方法，所以提前设置最高滑动距离
            if (measuredHeight > 0) {
                mDragViewMaxTopPosition = measuredHeight - maxDragHeight
            }
            requestLayout()
        }
    var mDragViewMaxTopPosition = 0 //可拖拽view的最大高度位置
    var mDragViewMinTopPosition = 0// 可拖拽view的关闭时top位置

    var mDragViewTop = -1//可拖拽view的top位置

    var mDragViewState = DragViewState.CLOSE

    var mDragViewOpenRatio = 0f


    var mOpenRatioListener: ((ratio: Float) -> Unit)? = null

    fun setOpenRatioListener(result: (ratio: Float) -> Unit) {
        mOpenRatioListener = result
    }


    override fun onFinishInflate() {
        super.onFinishInflate()
        mContentView = getChildAt(0)
        mDragView = getChildAt(1)

        mDragHelper = ViewDragHelper.create(this, 1f, object : ViewDragHelper.Callback() {
            override fun tryCaptureView(child: View, pointerId: Int): Boolean {
                if (child == mDragView) {
                    "tryCaptureView  mDragView".log("DragViewLayout")
                    return true
                }
                return false
            }

            override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
                val resultTop = top.let {
                    if (it < mDragViewMaxTopPosition) mDragViewMaxTopPosition else if (it > height) height else it
                }

                "clampViewPositionVertical $top $resultTop $mDragViewTop".log("DragViewLayout")

                return resultTop
            }


            override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
                super.onViewReleased(releasedChild, xvel, yvel)
                mDragViewTop = mDragView.top
                if (yvel > 2000) {
                    close()
                } else {
                    if (mDragViewOpenRatio > .5f) {
                        mDragHelper.settleCapturedViewAt(0, mDragViewMaxTopPosition)
                    } else {
                        mDragHelper.settleCapturedViewAt(0, mDragViewMinTopPosition)
                    }

                    invalidate()
                }
            }


            override fun onViewPositionChanged(
                changedView: View,
                left: Int,
                top: Int,
                dx: Int,
                dy: Int
            ) {
                super.onViewPositionChanged(changedView, left, top, dx, dy)
                updateRadio()
            }
        })
    }


    override fun computeScroll() {
        if (mDragHelper.continueSettling(true)) {
            updateRadio()
            invalidate()
        } else {
            //更新状态
            if (mDragView.top == mDragViewMaxTopPosition) {
                mDragViewState = DragViewState.OPEN
            } else if (mDragView.top == mDragViewMinTopPosition) {
                mDragViewState = DragViewState.CLOSE
            } else {
                mDragViewState = DragViewState.OPENING
            }
        }
    }

    private fun updateRadio() {
        mDragViewTop = mDragView.top
        mDragViewOpenRatio =
            1 - ((mDragView.top - mDragViewMaxTopPosition) * 1f / (mDragViewMinTopPosition - mDragViewMaxTopPosition))

        mOpenRatioListener?.also {
            it(mDragViewOpenRatio)
        }
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mDragView.measure(
            widthMeasureSpec, MeasureSpec.makeMeasureSpec(maxDragHeight, MeasureSpec.EXACTLY)
        )
        val parentHeight = MeasureSpec.getSize(heightMeasureSpec)
        mDragViewMaxTopPosition = parentHeight - maxDragHeight
        mDragViewMinTopPosition = parentHeight
        if (mDragViewTop == -1) {
            mDragViewTop = mDragViewMinTopPosition
        }
    }


    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        val contentView = getChildAt(0)
        contentView.layout(0, 0, contentView.measuredWidth, contentView.measuredHeight)
        "onLayout mDragViewTop $mDragViewTop".log("DragViewLayout")
        //隐藏状态
        mDragView.layout(
            0,
            mDragViewTop,
            mDragView.measuredWidth,
            mDragViewTop + mDragView.measuredHeight
        )

    }

    fun open() {
        mDragHelper.smoothSlideViewTo(mDragView, 0, mDragViewMaxTopPosition)
        postInvalidate()
    }

    fun close() {
        mDragHelper.smoothSlideViewTo(mDragView, 0, mDragViewMinTopPosition)
        postInvalidate()

    }


    var downY = 0f
    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        //打开情况下，点击内容区域，拦截事件，
        if (mDragViewState != DragViewState.CLOSE && mDragHelper.findTopChildUnder(
                ev.x.toInt(),
                ev.y.toInt()
            ) == mContentView
        ) {
            return true
        }
        "onInterceptTouchEvent  11111111".log("DragViewLayout")

        val shouldInterceptTouchEvent = mDragHelper.shouldInterceptTouchEvent(ev)
        "mDragHelper 判断是否拦截结果 $shouldInterceptTouchEvent".log("DragViewLayout")

        var onIntercept = false
        if (ev.action == MotionEvent.ACTION_DOWN) {
            downY = ev.y
            mDragHelper.processTouchEvent(ev)
            return false
        } else {
            var dirc = ev.y - downY
            //如果ziview 中包含能滚动的view ，先判断其是否已经滚动完毕，
            val touchView = mDragHelper.findTopChildUnder(ev.x.toInt(), ev.y.toInt())
            if (touchView == mDragView) {
                val isDown = dirc > 0
                //向下滑动时，先让内容先滑动完毕
                if (isDown) {
                    onIntercept = !finderCanScrollableView(mDragView, ev)
                } else {//向上滑动时，先确保dragview滑动到了顶部
                    //判断自己是否滑动到了顶部
                    onIntercept = mDragView.top > mDragViewMaxTopPosition
                }
            }
        }
        "自己判断是否拦截 $onIntercept".log("DragViewLayout")
        val interceptResult = shouldInterceptTouchEvent && onIntercept
        interceptResult.log("DragViewLayout")
        return interceptResult
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        "onTouchEvent  ".log("DragViewLayout")
        mDragHelper.processTouchEvent(event)
        if (mDragViewState != DragViewState.CLOSE && mDragHelper.findTopChildUnder(
                event.x.toInt(),
                event.y.toInt()
            ) == mContentView
        ) {
            if (event.action == MotionEvent.ACTION_UP) {
                close()
            }
            return true
        }

        return true
    }


    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        if (ev?.action == MotionEvent.ACTION_DOWN) {
            parent.requestDisallowInterceptTouchEvent(true)
        }

        if (mDragViewState != DragViewState.CLOSE) {
            parent.requestDisallowInterceptTouchEvent(true)
            "parent 不拦截事件".log()
            return super.dispatchTouchEvent(ev)
        } else {
            "parent 拦截事件".log()
            parent.requestDisallowInterceptTouchEvent(false)
            return super.dispatchTouchEvent(ev)
        }

    }

    private fun finderCanScrollableView(view: View, ev: MotionEvent): Boolean {
        if(view is ScrollingView){
            return view.canScrollVertically(-1)
        }
        //根据点击位置查找当前点击的view
        if (view is ViewGroup) {
            val childUnder = findTopChildUnder(view, ev.x.toInt(), ev.y.toInt()) ?: return false
            return if (childUnder is ScrollingView) {
                childUnder.canScrollVertically(-1)
            } else {
                finderCanScrollableView(childUnder, ev)
            }
        } else {
            return view.canScrollVertically(-1)
        }
    }

    private fun findTopChildUnder(mParentView: ViewGroup, x: Int, y: Int): View? {
        val childCount: Int = mParentView.childCount
        for (i in childCount - 1 downTo 0) {
            val child: View = mParentView.getChildAt(i)
            if (x >= child.left && x < child.right && y >= child.top && y < child.bottom) {
                return child
            }
        }
        return null
    }

}
